#pragma once
#include <string>
#include "PlayerColor.h"
#include "DieNumber.h"

namespace catan
{
	struct ProtocolBase
	{
		virtual int Type() = 0;
	};

	template <int value>
	struct Protocol : public ProtocolBase
	{

//  		template<class Serializer>
//  		void serialize(Serializer & s, const unsigned int version)
//  		{
//  			VALID(0); return;
//  		}

// 		template <class Serializer>
// 		int Serialize(Serializer& s){VALID(0); return 0;}

		virtual ~Protocol(void){}
		virtual int Type() {return value;}
		enum {TypeValue = value};
	};

	struct Result
	{
		enum Enum 
		{
			Succeed,
			Error,
		};
		static tstring ToString(Result::Enum r)
		{

			switch(r)
			{
			CASE_RetString(Succeed);
			CASE_RetString(Error);
			}
			VALID(0);
			return _T("");
		}
	};
	struct DieReq : Protocol<0>
	{
		PlayerColor::Enum mColor;	

		template<class Serializer>
		void serialize(Serializer & s, const unsigned int version)
		{
			s & mColor;
		}

	};

	struct DieApply : Protocol<1>
	{
		DieNumber mDieNumber;
		template<class Serializer>
		void serialize(Serializer & s, const unsigned int version)
		{
			s & mDieNumber;
		}
	};

	struct UseCardReq : Protocol<2>
	{
		PlayerColor::Enum mColor;
		Handle<DevelopmentCard> mDevelopmentCard;

	};

	struct UseCardApply : Protocol<3>
	{

	};

	struct BuyCardReq : Protocol<4>
	{
		PlayerColor::Enum mColor;
	};

	struct BuyCardApply : Protocol<5>
	{
		PlayerColor::Enum mColor;
		Handle<DevelopmentCard> mDevelopmentCard;
		template<class Serializer>
		void serialize(Serializer & s, const unsigned int version)
		{
			s & mColor & mDevelopmentCard;
		}
	};

	template <int value>
	struct BuildReqBase : Protocol<value>
	{
		PlayerColor::Enum mColor;
		int mId;

		template<class Serializer>
		void serialize(Serializer & s, const unsigned int version)
		{
			s & mColor & mId;
		}
	};

	template <int value, class DevierdApply>
	struct BuildApplyBase : Protocol<value>
	{
		template <class ReqBase>
		static DevierdApply FromReq(ReqBase& req)
		{
			DevierdApply apply;
			apply.mResult = Result::Succeed;
			apply.mColor = req.mColor;
			apply.mId = req.mId;
			return apply;
		}
		Result::Enum mResult;
		PlayerColor::Enum mColor;
		int mId;

		template<class Serializer>
		void serialize(Serializer & s, const unsigned int version)
		{
			s & mResult & mColor& mId;
		}
	};


	struct BuildHouseReq : BuildReqBase<6>
	{
	};

	struct BuildHouseApply : BuildApplyBase<7, BuildHouseApply>
	{
	};

	struct BuildSettlementReq : BuildReqBase<8>
	{
		
	};

	struct BuildSettlementApply : BuildApplyBase<9, BuildSettlementApply>
	{

	};

	struct BuildRoadReq : BuildReqBase<10>
	{
	};

	struct BuildRoadApply : BuildApplyBase<11, BuildRoadApply>
	{
	};

	struct EndTurnReq : Protocol<12>
	{
		PlayerColor::Enum mColor;
		template<class Serializer>
		void serialize(Serializer & s, const unsigned int version)
		{
			s & mColor ;
		}
	};

	struct EndTurnApply : Protocol<13>
	{
		Result::Enum mResult;
		PlayerColor::Enum mColor;
		template<class Serializer>
		void serialize(Serializer & s, const unsigned int version)
		{
			s & mResult & mColor;
		}
	};

	struct SetBuildRoad : Protocol<14>
	{
		
	};

	struct SetBuildHouse : Protocol<15>
	{
	};

	struct SetBuildSettlement : Protocol<16>
	{

	};

	struct SetGameEnd : Protocol<17>
	{

	};

	struct SetGameStart : Protocol<18>
	{
		template<class Serializer>
		void serialize(Serializer & s, const unsigned int version)
		{
			s & mBoard;
		}
// 		template <class Serializer>
// 		int Serialize(Serializer& s)
// 		{ 
// 			int i = 123456789;
// 			s & i;
// 			return 0;
// 		}
		Handle<Board> mBoard;
	};

	struct SetPlayerTrun : Protocol<19>
	{
		PlayerColor::Enum mColor;
		template<class Serializer>
		void serialize(Serializer & s, const unsigned int version)
		{
			s & mColor;
		}
	};

	struct PlayersHarvestApply : Protocol<20>
	{
		PlayersHarvestResourceCards* playersHarvestResourceCards;
		template<class Serializer>
		void serialize(Serializer & s, const unsigned int version)
		{
			s & playersHarvestResourceCards;
		}
	};
}	